package com.ygg.cps.afx.jdbc ;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.log4j.Logger;

import com.ygg.cps.afx.constant.DBConst;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class ConnectionManager
{
    
    private ConnectionManager()
    {
    }
    
    /**
     * 保存数据库连接池，可以配多个连接池
     */
    private final static ConcurrentMap<String, ComboPooledDataSource> dataSourceMap = new ConcurrentHashMap<String, ComboPooledDataSource>();
    
    private static Logger log = Logger.getLogger(ConnectionManager.class);
    
    /**
     * 保存初始化的配置文件,和 dataSourceMap 的key相同
     */
    private final static Map<String, String> connectionPoolProperties = new HashMap<String, String>();
    
    static
    {
        initConfigFiles();
    }
    
    private static void initConfigFiles()
    {
        connectionPoolProperties.put(DBConst.C3P0_CONNECTION_POOL, DBConst.dbC3p0config);
    }
    
    /**
     * 把Connection放入当前线程中，控制事务
     */
    private static final ThreadLocal<Connection> transactionHolder = new ThreadLocal<Connection>();
    
    private static void init(String connectionPoolKey)
    {
        
        if (!connectionPoolProperties.containsKey(DBConst.C3P0_CONNECTION_POOL))
            initConfigFiles();
        
        if (connectionPoolKey.equals(DBConst.C3P0_CONNECTION_POOL))
            initC3P0();
        
    }
    
    public static Connection getConnection(String connectionPoolKey)
        throws SQLException
    {
        Connection conn = transactionHolder.get();
        if (conn == null)
        {
            if (!dataSourceMap.containsKey(connectionPoolKey))
            {
                init(connectionPoolKey);
            }
            ComboPooledDataSource dataSource = dataSourceMap.get(connectionPoolKey);
            try
            {
                conn = dataSource.getConnection();
            }
            catch (SQLException e)
            {
                log.error("从" + connectionPoolKey + "数据库连接池获取连接出错", e);
                throw e;
            }
        }
        return conn;
    }
    
    /**
     * 从当前线程中得到Connection
     * 
     * @param connectionPoolKey
     * @return
     * @throws SQLException
     */
    public static Connection getCurrentConnection(String connectionPoolKey)
        throws SQLException
    {
        Connection conn = transactionHolder.get();
        return conn;
    }
    
    public static void beginTransaction(String connectionPoolKey)
    {
        if (!dataSourceMap.containsKey(connectionPoolKey))
        {
            init(connectionPoolKey);
        }
        ComboPooledDataSource dataSource = dataSourceMap.get(connectionPoolKey);
        try
        {
            Connection conn = dataSource.getConnection();
            conn.setAutoCommit(false);
            transactionHolder.set(conn);
        }
        catch (SQLException e)
        {
            log.error("beginTransaction:从" + connectionPoolKey + "数据库连接池获取连接出错", e);
        }
    }
    
    public static void commitTransaction()
    {
        Connection conn = (Connection)transactionHolder.get();
        if (conn != null)
        {
            try
            {
                conn.commit();
            }
            catch (SQLException e)
            {
                log.error("commit出错", e);
            }
            finally
            {
                try
                {
                    conn.close();
                }
                catch (SQLException e)
                {
                    log.error("close出错", e);
                }
                transactionHolder.remove();
            }
        }
    }
    
    /**
     * 对于查询方法,复用同一个Connection去查询,和releaseConnection成对使用
     * 
     * @param connectionPoolKey
     * @return
     * @throws SQLException
     */
    public static void beginQueryConnection(String connectionPoolKey)
        throws SQLException
    {
        if (!dataSourceMap.containsKey(connectionPoolKey))
        {
            init(connectionPoolKey);
        }
        ComboPooledDataSource dataSource = dataSourceMap.get(connectionPoolKey);
        try
        {
            Connection conn = dataSource.getConnection();
            transactionHolder.set(conn);
        }
        catch (SQLException e)
        {
            log.error("beginQueryConnection:从" + connectionPoolKey + "数据库连接池获取连接出错", e);
        }
        
    }
    
    /**
     * 对于查询方法,使用完以后,一定要调用此方法释放掉同一个Connection的连接,和getQueryConnection成对使用
     */
    public static void releaseConnection()
    {
        Connection conn = (Connection)transactionHolder.get();
        if (conn != null)
        {
            try
            {
                conn.close();
            }
            catch (SQLException e)
            {
                log.error("close出错", e);
            }
            transactionHolder.remove();
        }
    }
    
    public static void rollbackTransaction()
    {
        Connection conn = (Connection)transactionHolder.get();
        if (conn != null)
        {
            try
            {
                conn.rollback();
            }
            catch (SQLException e)
            {
                log.error("rollback出错", e);
            }
            finally
            {
                try
                {
                    conn.close();
                }
                catch (SQLException e)
                {
                    
                    log.error("close出错", e);
                }
                transactionHolder.remove();
            }
        }
    }
    
    private static void initC3P0()
    {
        if (dataSourceMap.containsKey(DBConst.C3P0_CONNECTION_POOL))
        {
            return;
        }
        if (!connectionPoolProperties.containsKey(DBConst.C3P0_CONNECTION_POOL))
            initConfigFiles();
        
        String dbConfig = connectionPoolProperties.get(DBConst.C3P0_CONNECTION_POOL);
        try
        {
            Properties p = new Properties();
            if (dbConfig.indexOf(".") > 0)
                p.load(ConnectionManager.class.getClassLoader().getResourceAsStream(dbConfig));
            else
                p.load(ConnectionManager.class.getClassLoader().getResourceAsStream(dbConfig + ".properties"));
            
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(p.getProperty("driverClassName"));
            dataSource.setJdbcUrl(p.getProperty("url"));
            dataSource.setUser(p.getProperty("username"));
            dataSource.setPassword(p.getProperty("password"));
            dataSource.setInitialPoolSize(Integer.valueOf(p.getProperty("initialPoolSize")));
            dataSource.setMinPoolSize(Integer.valueOf(p.getProperty("minPoolSize")));
            dataSource.setAcquireIncrement(Integer.valueOf(p.getProperty("acquireIncrement")));
            dataSource.setMaxPoolSize(Integer.valueOf(p.getProperty("maxPoolSize")));
            dataSource.setMaxStatements(Integer.valueOf(p.getProperty("maxStatements")));
            dataSource.setIdleConnectionTestPeriod(Integer.valueOf(p.getProperty("idleConnectionTestPeriod")));
            dataSource.setMaxIdleTime(Integer.valueOf(p.getProperty("maxIdleTime")));
            dataSourceMap.put(DBConst.C3P0_CONNECTION_POOL, dataSource);
        }
        catch (Exception e)
        {
            log.error("初始化c3p0数据库连接池出错", e);
        }
    }
    /*
     * private static void initDruid(String dbConfig) {
     * 
     * }
     */
    
}
